﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;
using System.Xml;
using System.Xml.Serialization;
using MediaPortal.GUI.Library;

namespace Burn4You
{
    public interface IExtension
    {
        string ExtName{get;}
        string Image{get;}
        List<String> SupportedBurnTypes();
        bool HasFiles { get; }
        bool HasUI { get; }
    }

    public class ExtensionHandler
    {
        public List<Extension> Extensions;
        private int ExtCount = 0;
        private int BurnTypeCount = 0;

        public ExtensionHandler()
        {
            LoadExtensions();
        }

        public void LoadExtensions()
        {
            String[] ExtFiles = Directory.GetFiles(Burn4YouPlugin.settings.ExtensionsDir, "*.DLL");
            Extensions = new List<Extension>();

            foreach (String ExtFile in ExtFiles)
            {
                Assembly asm;
                asm = Assembly.LoadFile(ExtFile);
                Type[] types = asm.GetTypes();

                if (asm != null)
                {
                    foreach (Type t in types)
                    {
                        if (typeof(IExtension).IsAssignableFrom(t))
                        {
                            Utils.Burn4YouLog.Write("Found a suitable extension");

                            Extension ext = (Extension)Activator.CreateInstance(t);
                            //ext.ExtInterface = (IExtension)Activator.CreateInstance(t);
                            ext.ExtInterface = (IExtension)ext;
                            ext.ID = ExtCount;
                            ExtCount++;
                            Extensions.Add(ext);
                        }
                    }
                }
            }

            foreach (Extension ext in Extensions)
                LoadNewExtension(ext);

            LoadBurnTypesXML();
        }

        private void LoadNewExtension(Extension ext)
        {
            List<String> SupportedBurnTypes = ext.ExtInterface.SupportedBurnTypes();

            foreach (String SupportedBurnType in SupportedBurnTypes)
            {
                bool isNew = true;

                foreach (BurnType bt in Burn4YouPlugin.BurnTypes)
                {
                    if (bt.Name == SupportedBurnType)
                        isNew = false;
                }


                if (isNew)
                    NewBurnType(SupportedBurnType);

                // add this extension to the burn types support list.
                for (int i = 0; i < Burn4YouPlugin.BurnTypes.Count; i++)
                {
                    if (Burn4YouPlugin.BurnTypes[i].Name == SupportedBurnType)
                    {
                        Burn4YouPlugin.BurnTypes[i].SupportingExtenstions.Add(ext.ID);
                    }
                }

            }

            // load Extension Window
            if (ext.ExtInterface.HasUI)
            {
                Utils.Burn4YouLog.Write("Registering extension \"" + ext.ExtInterface.ExtName + "\" to MediaPortal Window Manager.");
                GUIWindow window = ext;
                window.Init();
                GUIWindowManager.Add(ref window);
            }

            //Get the files the extension knowns about that can be burnt.
            if (ext.ExtInterface.HasFiles)
            {
                Utils.Burn4YouLog.Write("Attempting to get list of known files from extension \"" + ext.ExtInterface.ExtName + "\"");
                List<BurnFile> ExtKnownFiles = ext.GetFiles();
                Utils.Burn4YouLog.Write("Retrieved " + ExtKnownFiles.Count.ToString() + " files from " + ext.ExtInterface.ExtName);
                foreach (BurnFile File in ExtKnownFiles)
                {
                    if (!Burn4YouPlugin.Files.Contains(File))
                        Burn4YouPlugin.Files.Add(File);
                }
            }
        }

        private void NewBurnType(String Name)
        {
            BurnType NewBurnType = new BurnType();
            NewBurnType.Name = Name;
            NewBurnType.ID = BurnTypeCount;
            NewBurnType.SupportingExtenstions = new List<int>();

            BurnTypeCount++;

            Burn4YouPlugin.BurnTypes.Add(NewBurnType);
        }

        private void LoadBurnTypesXML()
        {
            XmlReader reader = null;
            XmlSerializer serializer = new XmlSerializer(typeof(BurnTypesXML));

            XmlReaderSettings ReaderSettings = new XmlReaderSettings();

            try
            {
                reader = XmlReader.Create(Burn4YouPlugin.settings.BurnTypesXML, ReaderSettings);
            }
            catch (Exception ex)
            {
                Utils.Burn4YouLog.Write("ERROR: Could not read BurnTypes XML file. File Location: " + Burn4YouPlugin.settings.BurnTypesXML + " Error message: " + ex.ToString());
                return;
            }

            BurnTypesXML btxml = (BurnTypesXML)serializer.Deserialize(reader);

            reader.Close();

            BurnTypesBurnTypeXML[] BurnTypesList = btxml.BurnType;

            foreach (BurnTypesBurnTypeXML BurnTypeXML in BurnTypesList)
            {
                Utils.Burn4YouLog.Write("Found BurnTypeXML config called " + BurnTypeXML.Name);
                for (int i = 0; i < Burn4YouPlugin.BurnTypes.Count; i++)
                {
                    if (Burn4YouPlugin.BurnTypes[i].Name == BurnTypeXML.Name)
                    {
                        Burn4YouPlugin.BurnTypes[i].Image = BurnTypeXML.Image;
                    }
                }
            }
        }
    }
}
